<?php

namespace support\Backend;

use support\Db;
use support\Model;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder as QueryBuilder;
use support\Exception\BusinessException;

/**
 * model 基类
 */
class BackendModel extends Model
{
    /**
     * 格式化日期
     *
     * @param DateTimeInterface $date
     * @return string
     */
    protected function serializeDate(DateTimeInterface $date): string
    {
        return $date->format('Y-m-d H:i:s');
    }
    public function setCreateTimeAttribute($value)
    {
        $this->attributes['create_time'] = is_int($value) ? $value : strtotime($value);
    }

    public function getCreateTimeAttribute()
    {
        return date('Y-m-d H:i:s', $this->attributes['create_time']);
    }
    public function getUpdateTimeAttribute()
    {
        return date('Y-m-d H:i:s', $this->attributes['update_time']);
    }
    public function setUpdateTimeAttribute($value)
    {
        $this->attributes['update_time'] = is_int($value) ? $value : strtotime($value);
    }
    /**
     * 格式化表数据
     * @param array $data 数据源
     * @param int $id 记录ID
     * @return array 返回结果
     * @author bh
     * @date 2024-12-24
     */
    public function formatData(&$data = [], $id = 0)
    {
        $data_list = [];
        //获取表名
        $table = $this->getConnection()->getTablePrefix() . $this->getTable();
        $item_data = [];
        $temp_data = [];
        $table_fields_list = $this->getTableFieldsList($table);
        foreach ($table_fields_list as $field => $field_info) {
            if ($field == "id") {
                continue;
            }
            // 强制类型转换
            if (isset($data[$field])) {
                if ($field_info['Type'] == "int") {
                    $item_data[$field] = (int)$data[$field];
                } else {
                    $item_data[$field] = (string)$data[$field];
                }
            }
            if (!isset($data[$field]) && in_array($field, array('update_time', 'create_time'))) {
                continue;
            }
            // 插入数据-设置默认值
            if (!$id && !isset($data[$field])) {
                $item_data[$field] = $field_info['Default'];
            }
            if (isset($item_data[$field])) {
                $temp_data[$field] = $item_data[$field];
            }
        }
        $data_list[] = $temp_data;
        $data = $item_data;
        return $data_list;
    }

    /**
     * 获取表字段
     * @param string $table 数据表名称
     * @return array 表字段
     * @author bh
     * @date 2024-12-24
     */
    private function getTableFieldsList($table = ''): array
    {
        $table = $table ?: $this->getConnection()->getTablePrefix() . $this->getTable();
        $field_list = $this->getConnection()->select("SHOW FIELDS FROM `$table`");
        $field_list = toArray($field_list);
        $info_list = [];
        if (!$field_list) return $info_list;
        foreach ($field_list as $row) {
            if ((!str_contains($row['Type'], "int")) ||
                (str_contains($row['Type'], "bigint"))
            ) {
                $type = "string";
                $default = $row['Default'] ?: "";
            } else {
                $type = "int";
                $default = $row['Default'] ?: 0;
            }
            $info_list[$row['Field']] = array(
                'Type' => $type,
                'Default' => $default
            );
        }
        return $info_list;
    }

    /**
     * 执行查询
     * @param array $where
     * @param string|null $field
     * @param string $order
     * @return EloquentBuilder|QueryBuilder|Model
     */
    protected function doSelect(array $where, array $field = ['*'], array $order = []): EloquentBuilder|Model|QueryBuilder
    {
        $model = $this->query()->select($field);
        if ($where) {
            foreach ($where as $column => $value) {
                if (!is_array($value)) {
                    $model->where($column, $value);
                } else {
                    if (in_array($value[1], ['>', '=', '<', '<>', 'like', 'not like', '>=', '<='])) {
                        $model = $model->where($value[0], $value[1], $value[2]);
                    } elseif ($value[1] == 'in') {
                        $model = $model->whereIn($value[0], is_array($value[2]) ? $value[2] : [$value[2]]);
                    } elseif ($value[1] == 'not in') {
                        $model = $model->whereNotIn($value[0], is_array($value[2]) ? $value[2] : [$value[2]]);
                    } elseif ($value[1] == 'null') {
                        $model = $model->whereNull($value[0], $value[2]);
                    } elseif ($value[1] == 'not null') {
                        $model = $model->whereNotNull($value[0], $value[2]);
                    } else if ($value[1] == 'between') {
                        $model = $model->whereBetween($value[0], $value[2]);
                    } else {
                        $model = $model->whereBetween($column, $value);
                    }
                }
            }
        }
        if ($order) {
            foreach ($order as $ocolumn => $ovalue) {
                $model = $model->orderBy($ocolumn, $ovalue);
            }
        }
        return $model;
    }


    /**
     * 分页查询
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param array $order 排序字段
     * @param array $with 关联模型
     * @param int $limit 限制条数
     * @param string $page 页面字段
     * @return array
     */
    public function getPaginateList(array $where, array $field = ['*'], array $order = [], array $with = [], $limit = 10, $page = 'page'): array
    {
        $paginate = $this->doSelect($where, $field, $order);
        if ($with) {
            $paginate = $paginate->with($with);
        }
        return $this->setPaginate($paginate->paginate($limit));
    }

    /**
     * 获取全部列表
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param array $order 排序字段
     * @param array $with 关联模型
     * @return array
     */
    public function getAllList(array $where, array $field = ['*'], array $order = [], array $with = []): array
    {
        $list = $this->doSelect($where, $field, $order);
        if ($list) {
            $list = $list->with($with);
        }
        $list = $list->get();
        return $list ? $list->toArray() : [];
    }

    /**
     * 添加单条数据
     * @param $param
     * @return int
     */
    public function insertOne($param): int
    {

        $now = time();
        if (!isset($param['create_time'])) {
            $param['create_time'] = $now;
        }
        if (!isset($param['update_time'])) {
            $param['update_time'] = $now;
        }
        return $this->query()->insertGetId($param);
    }

    /**
     * 添加多条数据
     * @param $param
     * @return bool
     */
    public function insertBatch($param): bool
    {

        return $this->query()->insert($param);
    }


    /**
     * 根据id更新数据
     * @param array $param
     * @param int $id
     * @return int
     */
    public function updateById(array $param, int $id): int
    {
        $pk = $this->getKeyName();
        //添加更新时间
        if (isset($param['create_time'])) {
            unset($param['create_time']);
        }
        if (!isset($param['update_time'])) {
            $param['update_time'] = time();
        }
        return $this->query()->where($pk, $id)->update($param);
    }

    /**
     * 根据条件更新数据
     * @param array $param 更新数据
     * @param array $where 查询条件
     * @return bool|int
     */
    public function updateByWhere(array $param, array $where): bool|int
    {
        //添加更新时间
        if (isset($param['create_time'])) {
            unset($param['create_time']);
        }
        if (!isset($param['update_time'])) {
            $param['update_time'] = time();
        }
        return $this->doSelect($where)->update($param);
    }

    /**
     * 根据id集合更新数据
     * @param array $param
     * @param array $ids
     * @return int
     */
    public function updateByIds(array $param, array $ids): int
    {
        $pk = $this->getKeyName();
        if (isset($param['create_time'])) {
            unset($param['create_time']);
        }
        if (!isset($param['update_time'])) {
            $param['update_time'] = time();
        }
        return $this->query()->whereIn($pk, $ids)->update($param);
    }

    /**
     * 根据id删除数据
     * @param $id
     * @return bool
     */
    public function delById($id): bool
    {
        $pk = $this->getKeyName();
        return $this->query()->where($pk, $id)->delete();

    }

    /**
     * 根据id删除
     * @param array $ids
     * @return
     */
    public function delByIds(array $ids)
    {
        $pk = $this->getKeyName();
        return $this->query()->whereIn($pk, $ids)->delete();

    }

    /**
     * 根据条件删除
     * @param array $where 查询条件
     * @return bool
     */
    public function delByWhere(array $where): bool
    {
        return $this->doSelect($where)->delete();
    }


    /**
     * 根据id获取信息
     * @param int $id 主键ID
     * @param array $field
     * @return array
     */
    public function getInfoById(int $id, array $field = ['*']): array
    {
        $primary_key = $this->getKeyName();
        if (!$primary_key) {
            throw new BusinessException('该表无主键，不支持查询');
        }
        return $this->getInfoByWhere([$primary_key => $id], $field);

    }

    /**
     * 根据查询条件获取信息
     * @param array $where 查询条件
     * @param array $field 查询字段
     * @param array $order 排序字段
     * @return array
     */
    public function getInfoByWhere(array $where, array $field = ['*'], array $order = []): array
    {
        $info = $this->doSelect($where, $field, $order)->first();
        return $info ? $info->toArray() : [];
    }

    /**
     * 检测数据唯一
     * @param array $where 查询条件
     * @param int $id 当前操作ID
     * @return array
     */
    public function checkUnique(array $where, int $id = 0)
    {
        if (empty($id)) {
            $has = $this->doSelect($where)->first();
        } else {
            $pk = $this->getKeyName();
            $has = $this->doSelect($where)->where([$pk, '<>', $id])->first();
        }
        return $has ? $has->toArray() : [];
    }


    /**
     * 设置后台分页数据格式
     * @param  $paginate
     * @return array
     */
    protected function setPaginate($paginate): array
    {
        return [
            'list' => toArray($paginate->items()),
            'total' => $paginate->total(),
            'last_page' => $paginate->lastPage(),
            'per_page' => $paginate->perPage(),
            'current_page' => $paginate->currentPage()
        ];
    }

    /**
     * 根据查询条件获取数量
     * @param array $where 查询条件
     * @return int
     */
    public function getCountByWhere(array $where): int
    {
        return $this->doSelect($where)->count();
    }

}